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

mongodb-js / mongodb-mcp-server / 16056999906

03 Jul 2025 05:34PM UTC coverage: 75.743% (+1.5%) from 74.286%
16056999906

Pull #339

github

web-flow
Merge dd6dadd52 into d7d4aa9ae
Pull Request #339: chore: reinstate telemetry/docker change after revert (MCP-49)

235 of 394 branches covered (59.64%)

Branch coverage included in aggregate %.

17 of 21 new or added lines in 1 file covered. (80.95%)

3 existing lines in 2 files now uncovered.

836 of 1020 relevant lines covered (81.96%)

59.11 hits per line

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

65.96
/src/tools/atlas/metadata/connectCluster.ts
1
import { z } from "zod";
2
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
import { AtlasToolBase } from "../atlasTool.js";
4
import { ToolArgs, OperationType } from "../../tool.js";
5
import { generateSecurePassword } from "../../../common/atlas/generatePassword.js";
6
import logger, { LogId } from "../../../logger.js";
7
import { inspectCluster } from "../../../common/atlas/cluster.js";
8

9
const EXPIRY_MS = 1000 * 60 * 60 * 12; // 12 hours
34✔
10

11
function sleep(ms: number): Promise<void> {
12
    return new Promise((resolve) => setTimeout(resolve, ms));
×
13
}
14
export class ConnectClusterTool extends AtlasToolBase {
15
    protected name = "atlas-connect-cluster";
33✔
16
    protected description = "Connect to MongoDB Atlas cluster";
33✔
17
    protected operationType: OperationType = "metadata";
33✔
18
    protected argsShape = {
33✔
19
        projectId: z.string().describe("Atlas project ID"),
20
        clusterName: z.string().describe("Atlas cluster name"),
21
    };
22

23
    protected async execute({ projectId, clusterName }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
24
        await this.session.disconnect();
1✔
25

26
        const cluster = await inspectCluster(this.session.apiClient, projectId, clusterName);
1✔
27

28
        if (!cluster.connectionString) {
1!
UNCOV
29
            throw new Error("Connection string not available");
×
30
        }
31

32
        const username = `mcpUser${Math.floor(Math.random() * 100000)}`;
1✔
33
        const password = await generateSecurePassword();
1✔
34

35
        const expiryDate = new Date(Date.now() + EXPIRY_MS);
1✔
36

37
        const readOnly =
38
            this.config.readOnly ||
1!
39
            (this.config.disabledTools?.includes("create") &&
40
                this.config.disabledTools?.includes("update") &&
41
                this.config.disabledTools?.includes("delete") &&
42
                !this.config.disabledTools?.includes("read") &&
43
                !this.config.disabledTools?.includes("metadata"));
44

45
        const roleName = readOnly ? "readAnyDatabase" : "readWriteAnyDatabase";
1!
46

47
        await this.session.apiClient.createDatabaseUser({
1✔
48
            params: {
49
                path: {
50
                    groupId: projectId,
51
                },
52
            },
53
            body: {
54
                databaseName: "admin",
55
                groupId: projectId,
56
                roles: [
57
                    {
58
                        roleName,
59
                        databaseName: "admin",
60
                    },
61
                ],
62
                scopes: [{ type: "CLUSTER", name: clusterName }],
63
                username,
64
                password,
65
                awsIAMType: "NONE",
66
                ldapAuthType: "NONE",
67
                oidcAuthType: "NONE",
68
                x509Type: "NONE",
69
                deleteAfterDate: expiryDate.toISOString(),
70
            },
71
        });
72

73
        this.session.connectedAtlasCluster = {
1✔
74
            username,
75
            projectId,
76
            clusterName,
77
            expiryDate,
78
        };
79

80
        const cn = new URL(cluster.connectionString);
1✔
81
        cn.username = username;
1✔
82
        cn.password = password;
1✔
83
        cn.searchParams.set("authSource", "admin");
1✔
84
        const connectionString = cn.toString();
1✔
85

86
        let lastError: Error | undefined = undefined;
1✔
87

88
        for (let i = 0; i < 20; i++) {
1✔
89
            try {
1✔
90
                await this.session.connectToMongoDB(connectionString, this.config.connectOptions);
1✔
91
                lastError = undefined;
1✔
92
                break;
1✔
93
            } catch (err: unknown) {
94
                const error = err instanceof Error ? err : new Error(String(err));
×
95

96
                lastError = error;
×
97

98
                logger.debug(
×
99
                    LogId.atlasConnectFailure,
100
                    "atlas-connect-cluster",
101
                    `error connecting to cluster: ${error.message}`
102
                );
103

104
                await sleep(500); // wait for 500ms before retrying
×
105
            }
106
        }
107

108
        if (lastError) {
1!
109
            throw lastError;
×
110
        }
111

112
        return {
1✔
113
            content: [
114
                {
115
                    type: "text",
116
                    text: `Connected to cluster "${clusterName}"`,
117
                },
118
            ],
119
        };
120
    }
121
}
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